local tabletool = require "tabletool"
local timetool = require "timetool"
local msghelper = require "tablehelper"
local timer = require "timer"
local filelog = require "filelog"
local skynet = require "skynet"
local cluster = require "skynet.cluster"
local math_floor = math.floor
local math_ceil = math.ceil

local json = require "cjson"
json.encode_sparse_array(true,1,1)

require "pdkenum"

local gamelogic
local seatlogic
local ddzlogic
local TableLogic = {}

function TableLogic.init(tablebase, conf)
	if conf == nil then
		filelog.sys_error("TableLogic.init conf = nil")
		return false
	end

	local table_data = tablebase.table_data
	gamelogic = tablebase.logic.gamelogic
	seatlogic = tablebase.logic.seatlogic

	if conf.game_type%2 == 0 then
		local ddzgamelogic = require "ddzgamelogic15"
		tablebase.logic.ddzlogic = ddzgamelogic:new()
		conf.hand_cards_num = 15
	else
		local ddzgamelogic = require "ddzgamelogic"
		tablebase.logic.ddzlogic = ddzgamelogic:new()
		conf.hand_cards_num = 16
	end
	ddzlogic = tablebase.logic.ddzlogic
	tablebase.update_logic(ddzlogic)

	table_data.idx = conf.idx
	table_data.state = ETableState.TABLE_STATE_WAIT_ALL_READY

	local seat
	local count = 1
    while count <= conf.max_player_num do
    	seat = {
    		index = 0,
			rid = 0,
			state = 0,  --该坐位玩家状态
			playerinfo = {
				rolename = "",
				logo = "",
				sex = 0,
				ip_addr = "",
				fangka = 0,
				diamond = 0,
			},
			is_tuoguan = 0,
			is_ready = EBOOL.FALSE,
    		--Add 座位其他变量
    		timeout_count = 0, --超时次数
    		win = 0,             ----表示玩家胜利还是失败
			diamond = 0,
			getdiamond = 0,
			fangka = 0,
    		ready_timer_id = -1, ----准备倒计时定时器
    		ready_to_time = 0,   ----准备到期时间
			cards = {},		     ----玩家手牌
			handcards = {},		 ----初始手牌
			multiple = 0,		 ----玩家加倍倍数
			balance_score = 0,	 ----最终结算分数
			tuoguan_punish = 0, 
			followhandsnum = 0,
			holdvalue = 0, 		 ----玩家货币持有量
			dealnum = 0, 		 ----玩家中间结算量
			foundtime = 0,       ----开始发牌时间 
    	}
    	seatlogic.init(seat, count)
    	table.insert(table_data.seats, seat) 
		count = count + 1
    end
	table_data.conf = tabletool.deepcopy(conf)
	table_data.the_round = 1   --当前游戏轮数
	table_data.playernum = 0 --玩家数量

	table_data.gamelogic = {table_data = nil, stateevent = {},}
	gamelogic.init(table_data.gamelogic, tablebase)
	return true
end

function TableLogic.checkallonline(table_data)
	local online = false
	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			if not seat.is_disconnect then
				online = true
				break
			end
		end
	end
	if not online then
		if table_data.timer_id > 0 then
			timer.cleartimer(table_data.timer_id)
			table_data.timer_id = -1
		end
		for _, seat in ipairs(table_data.seats) do
			if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
				TableLogic.passive_standuptable(table_data, seat)
			end
		end
	end
	return online
end

function TableLogic.disconnect(table_data, request, seat)
	if not table_data.conf.match_type and (seat.state == ESeatState.SEAT_STATE_WAIT_READY or seat.state == ESeatState.SEAT_STATE_WATCHING) then
		TableLogic.passive_standuptable(table_data, seat)
	else
		if table_data.conf.room_type == ERoomType.ROOM_TYPE_SYSTEM then
			TableLogic.passive_standuptable(table_data, seat)
		else
			seat.is_tuoguan = EBOOL.TRUE
			seat.is_disconnect = true
			-- if TableLogic.checkallonline(table_data) then
				msghelper:sendmsg_to_alltableplayer("disconnectN", {
					rid = seat.rid,
					seat_index = seat.index,
					is_tuoguan = seat.is_tuoguan,
				})
			-- end
		end
	end
end

function TableLogic.clear(table_data)
	if table_data.timer_id > 0 then
		timer.cleartimer(table_data.timer_id)
		table_data.timer_id = -1
	end

	if table_data.delete_table_timer_id > 0 then
		timer.cleartimer(table_data.delete_table_timer_id)
		table_data.delete_table_timer_id = -1
	end

	for k,v in pairs(table_data) do
		table_data[k] = nil
	end
end

--[[
	seat: nil表示否， 非nil表示是
--]]
function TableLogic.entertable(table_data, request, seat)
	if table_data.delete_table_timer_id and table_data.delete_table_timer_id > 0 then
		timer.cleartimer(table_data.delete_table_timer_id)
		table_data.delete_table_timer_id = -1
	end

	local rid = request.rid
	if seat then 
		if seat.is_tuoguan == EBOOL.TRUE then
			seat.is_tuoguan = EBOOL.FALSE
		end
	else
		if table_data.waits[rid] == nil then
			table_data.waits[rid] = {}
			table_data.waits[rid].playerinfo = {}
			table_data.cur_watch_playernum = table_data.cur_watch_playernum + 1			 
		end
		table_data.waits[rid].rid = rid
		table_data.waits[rid].playerinfo.rolename = request.playerinfo.rolename
		table_data.waits[rid].playerinfo.logo = request.playerinfo.rolename
		table_data.waits[rid].playerinfo.sex = request.playerinfo.sex
		if table_data.conf.match_type then
			table_data.waits[rid].waitreenter = 1
		end
	end
end

function TableLogic.reentertable(table_data, request, seat)
	msghelper:sendmsg_to_alltableplayer("disconnectN", {
		rid = seat.rid,
		seat_index = seat.index,
		is_tuoguan = EBOOL.FALSE,
	})

	if table_data.delete_table_timer_id and table_data.delete_table_timer_id > 0 then
		timer.cleartimer(table_data.delete_table_timer_id)
		table_data.delete_table_timer_id = -1
	end

	seat.sametabledata = request.countdata
	msghelper:sendmsg_to_alltableplayer("sametablecountN", {
		rid = seat.rid,
		countdata = seat.sametabledata
	})

	if not TableLogic.is_onegameend(table_data) then
		--通知玩家当前该他操作
		if table_data.action_seat_index == 0 then return end
		table_data.action_to_time = timetool.get_time() + table_data.conf.action_timeout
		local doactionntcmsg = {
			rid = table_data.seats[table_data.action_seat_index].rid,
			seat_index = table_data.action_seat_index,
			action_to_time = table_data.action_to_time,
			action_type = table_data.action_type,
		}
		msghelper:sendmsg_to_tableplayer(seat, "todoN", doactionntcmsg)
	end
end

function TableLogic.sitdowntable(table_data, request, seat)
	if table_data.waits[request.rid] then
		table_data.waits[request.rid] = nil
		table_data.cur_watch_playernum = table_data.cur_watch_playernum - 1
	end
	if table_data.conf.match_type then
		seat.waitreenter = 1
	end

	seat.rematched = nil
	seat.state = ESeatState.SEAT_STATE_WAIT_READY	--等待开始
	seat.rid = request.rid
	seat.playerinfo.rolename = request.playerinfo.rolename
	seat.playerinfo.logo = request.playerinfo.logo
	seat.playerinfo.sex = request.playerinfo.sex
	seat.playerinfo.ip_addr = request.playerinfo.ip_addr or ''
	seat.playerinfo.gps_addr = request.playerinfo.gps_addr or ''
	seat.playerinfo.fangka = request.money.fangka or 0
	seat.playerinfo.diamond = request.money.diamond or 0
	seat.playerinfo.coin = request.money.coin or 0
	seat.playerinfo.introduce = request.playerinfo.intro or ''
	seat.playerinfo.upvoted_num = request.playerinfo.upvoted_num or 0
	seat.playerinfo.downvoted_num = request.playerinfo.downvoted_num or 0
	seat.playerinfo.logoframe = request.playerinfo.logoframe
	seat.getfangka = request.money.fangka
	seat.diamond = request.money.diamond
	seat.getdiamond = seat.diamond
	if table_data.conf.room_type == ERoomType.ROOM_TYPE_FRIEND then
		seat.diamond = 0
		seat.getdiamond = 0
	elseif table_data.conf.room_type == ERoomType.ROOM_TYPE_SYSTEM then
		seat.diamond = 10000
		seat.getdiamond = 10000
	end

	local outoftimermsg = {
		rid = seat.rid,
		seat_index = seat.index,
	}
	seat.ready_timer_id = timer.settimer(table_data.conf.ready_timeout*100, "doready", outoftimermsg)
	seat.ready_to_time = timetool.get_time() + table_data.conf.ready_timeout

	if not table_data.conf.match_type or table_data.the_round > 1 then
		local noticemsg = {
			rid = seat.rid,
			seat = {},
			player_info = {},
		}
		msghelper:copy_seatinfo(noticemsg.seat, seat)
		msghelper:copy_playerinfo(noticemsg.player_info, seat)
		msghelper:sendmsg_to_alltableplayer("sitdowntableN", noticemsg)
	
		local doreadyntcmsg = {
			rid = seat.rid,
			seat_index = seat.index,
			ready_to_time = timetool.get_time() + table_data.conf.ready_timeout,
		}
		msghelper:sendmsg_to_alltableplayer("doreadyN", doreadyntcmsg)
	end

	if seat.is_tuoguan == EBOOL.TRUE then
		seat.is_tuoguan = EBOOL.FALSE
		--TO ADD 添加托管处理
	end
	if seat.rid > 0 and seat.rid < 100 then
		seat.is_tuoguan = EBOOL.TRUE
	end
	--增加桌子人数计数 
	table_data.sitdown_player_num = table_data.sitdown_player_num + 1
	table_data.playernum = table_data.playernum + 1
	if table_data.conf.room_type == ERoomType.ROOM_TYPE_COMMON then
		msghelper:sendmsg_to_roomsvr("update_table_player", 
			table_data.conf.idx,
			table_data.sitdown_player_num,
			table_data.conf.is_public,
			table_data.conf.match_type,
			table_data.conf.room_type
		)
	end

	-------------------------- robot --------------------------
	if request.playerinfo.level == 99 then
		seat.isrobot = true
		msghelper:sendmsg_to_roomsvr("change_robot_num", 1, table_data.conf.idx, table_data.conf.is_public, table_data.conf.match_type, table_data.conf.room_type)
		if table_data.sitdown_player_num == 1 and table_data.conf.create_user_rid == 101 then
			table_data.conf.name = seat.playerinfo.rolename .. "的房间"
	    	table_data.conf.rid = seat.rid
	    	table_data.conf.create_user_rid = rid
			table_data.conf.create_user_name = seat.playerinfo.rolename
	    	table_data.conf.create_user_logo = seat.playerinfo.logo
		end

		skynet.fork(function ()
			skynet.sleep(math.random(1, 4) * 100)
			TableLogic.gameready(table_data, {rid = seat.rid}, seat)
		end)
	end
end

function TableLogic.gameready(table_data, request, seat)
	if seat.ready_timer_id and seat.ready_timer_id > 0  then ---取消准备倒计时
		timer.cleartimer(seat.ready_timer_id)
		seat.ready_timer_id = -1
		seat.ready_to_time = 0
	end

	seat.state = ESeatState.SEAT_STATE_WAIT_START
	seat.is_ready = EBOOL.TRUE
	local noticemsg = {
		rid = seat.rid,
		seat_index = seat.index,
		isready = 1,
		table_state = 0,
	}
	noticemsg.table_state = table_data.state
	msghelper:sendmsg_to_alltableplayer("gamereadyN", noticemsg)
	
	if table_data.conf.match_type and request.rid > 100 then 	-- and table_data.the_round > 1 then
		if table_data.conf.game_type > 2 then
			if table_data.playernum <= 1 then
				skynet.call(".router","lua","restart_matchtable", {request.rid}, table_data.conf.match_type)
				TableLogic.passive_standuptable(table_data, seat)
			end
		else
			if table_data.playernum <= 2 then
				skynet.call(".router","lua","restart_matchtable", {request.rid}, table_data.conf.match_type)
				TableLogic.passive_standuptable(table_data, seat)
			end
		end
    end

	local isallready = true
	for k, v in ipairs(table_data.seats) do
		if v.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			if v.state ~= ESeatState.SEAT_STATE_WAIT_START then
				isallready = false
				break
			end
		end
	end
	-- filelog.debug("------ isallready ------", isallready)
	if isallready then
		TableLogic.startgame(table_data)
	end
end

function TableLogic.startgame(table_data, request)
	if TableLogic.is_canstartgame(table_data) then
		table_data.state = ETableState.TABLE_STATE_GAME_START
		table_data.gaming = true
		if table_data.conf.room_type == ERoomType.ROOM_TYPE_FRIEND then
			table_data.cur_games_times = table_data.cur_games_times + 1
		end
		gamelogic.run(table_data.gamelogic)
		filelog.warn("------ game start ------")
		return true
	else
		table_data.state = ETableState.TABLE_STATE_WAIT_ALL_READY
		return false
	end
end

--
--处理重新匹配
--
function TableLogic.restart_matchtable(table_data, rid)
	local rids = {}
	local ts = timetool.get_time()
	for k, v in ipairs(table_data.seats) do
		if v.rid > 100 and v.rid ~= rid and v.state == ESeatState.SEAT_STATE_WAIT_START and not v.rematched then
			if not v.ready_to_time or (v.ready_to_time == 0) or ts <= (v.ready_to_time - 1) then
				v.rematched = true
				table.insert(rids, v.rid)
			end
		end
	end
	local match_type = table_data.conf.match_type
	skynet.call(".router","lua","restart_matchtable", rids, match_type)
	for _, rid in ipairs(rids) do
		local seat = TableLogic.get_seat_by_rid(table_data, rid)
		TableLogic.passive_standuptable(table_data, seat, nil, true)
	end
end

function TableLogic.leaveallplayers(table_data)
	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			TableLogic.passive_standuptable(table_data, seat)
		end
	end
end

function TableLogic.leavetable(table_data, request, seat, re)
	local leavetablentc = {rid = request.rid}
	msghelper:sendmsg_to_alltableplayer("leavetableN", leavetablentc)
	msghelper:sendmsg_to_roomsvr("playerleavetable", request.rid, table_data.conf.game_room_type)
	if not table_data.conf.match_type and seat.isrobot then
		pcall(cluster.send, "robotnode", ".router", "request_robot_leave", "psznode", table_data.idx, {request.rid})
	end
	--匹配场
	-- if not table_data.recycled and table_data.conf.match_type and request.rid > 100 then
	-- 	table_data.recycled = true
	-- 	TableLogic.restart_matchtable(table_data, request.rid) --匹配场，将座位上玩家，加入匹配队列
	-- 	TableLogic.leaveallplayers(table_data)
	-- end
	if table_data.conf.match_type and request.rid > 100
		and (not table_data.delete_table_timer_id or table_data.delete_table_timer_id == -1) then
		if not re then
			TableLogic.restart_matchtable(table_data, request.rid) --匹配场，将座位上玩家，加入匹配队列
		end
    end
	if (table_data.playernum <= 0 or table_data.conf.room_type == ERoomType.ROOM_TYPE_SYSTEM)
			and (not table_data.delete_table_timer_id or table_data.delete_table_timer_id == -1) then
		local retain_time = table_data.conf.retain_time
		if table_data.conf.match_type then
			retain_time = 1
		end
		table_data.delete_table_timer_id = timer.settimer(retain_time*100, "delete_table")
		table_data.the_round = 1
		table_data.recycled = nil
		if table_data.timer_id and table_data.timer_id > 0 then
			timer.cleartimer(table_data.timer_id)
			table_data.timer_id = -1
		end
		for k,v in ipairs(table_data.seats) do
			if v.rid ~= 0 and (v.state == ESeatState.SEAT_STATE_WAIT_READY) then
				if v.ready_timer_id > 0 then
					timer.cleartimer(v.ready_timer_id)
					v.ready_timer_id = -1
				end
			end
		end
	end
	if table_data.waits[request.rid] then
		table_data.waits[request.rid] = nil
		table_data.cur_watch_playernum = table_data.cur_watch_playernum - 1
	end
end

function TableLogic.passive_standuptable(table_data, seat, reason, re)
	if not seat or seat.rid <= 0 or seat.standup then return end
	if not TableLogic.is_onegameend(table_data) then --一局游戏结束，is_onegameeend返回ture
		if gamelogic.is_ingame(table_data.gamelogic,seat) == true then
			seat.state = ESeatState.SEAT_STATE_ESCAPE
		end
	end
	local rid = seat.rid
	table_data.sitdown_player_num = table_data.sitdown_player_num - 1
	table_data.playernum = table_data.playernum - 1
	if table_data.sitdown_player_num < 0 then
		table_data.sitdown_player_num = 0
		table_data.playernum = 0
		filelog.sys_error("passive_standuptable: sitdown_player_num < 0 !!!", table_data.sitdown_player_num)
	end
	if table_data.conf.room_type == ERoomType.ROOM_TYPE_COMMON then
		msghelper:sendmsg_to_roomsvr("update_table_player", 
			table_data.conf.idx,
			table_data.sitdown_player_num,
			table_data.conf.is_public,
			table_data.conf.match_type,
			table_data.conf.room_type
		)
	end
	local noticemsg = {
		rid = rid, 
		seat_index = seat.index,
		state = seat.state,
		reason = reason,
	}
	msghelper:sendmsg_to_alltableplayer("standuptableN", noticemsg) --同知座位上的人，某位玩家离
	seat.standup = true
	-- if seat.index == table_data.winner then
		table_data.winner = nil
	-- end

	TableLogic.leavetable(table_data, {rid = rid}, seat, re)

	local isrobot = seat.isrobot
	if isrobot then
		msghelper:sendmsg_to_roomsvr("change_robot_num", -1, table_data.conf.idx, table_data.conf.is_public, table_data.conf.match_type, table_data.conf.room_type)
	end
	--初始化座位数据
	gamelogic.standup_clear_seat(table_data.gamelogic, seat)
end

function TableLogic.standuptable(table_data, request, seat)
	if not seat or seat.rid <= 0 then return end
	table_data.sitdown_player_num = table_data.sitdown_player_num - 1
	table_data.playernum = table_data.playernum - 1
	if table_data.sitdown_player_num < 0 then
		table_data.sitdown_player_num = 0
		table_data.playernum = 0
		filelog.sys_error("standuptable: sitdown_player_num < 0 !!!", table_data.sitdown_player_num)
	end
	if table_data.conf.room_type == ERoomType.ROOM_TYPE_COMMON then
		msghelper:sendmsg_to_roomsvr("update_table_player", 
			table_data.conf.idx,
			table_data.sitdown_player_num,
			table_data.conf.is_public,
			table_data.conf.match_type,
			table_data.conf.room_type
		)
	end
	local noticemsg = {
		rid = seat.rid, 
		seat_index = seat.index,
		state = seat.state,
		reason = EStandupReason.STANDUP_REASON_ONSTANDUP,
	}
	msghelper:sendmsg_to_alltableplayer("standuptableN", noticemsg)
	seat.standup = true
	-- if seat.index == table_data.winner then
		table_data.winner = nil
	-- end

	local isrobot = seat.isrobot
	if isrobot then
		msghelper:sendmsg_to_roomsvr("change_robot_num", -1, table_data.conf.idx, table_data.conf.is_public, table_data.conf.match_type, table_data.conf.room_type)
	end
	--初始化座位数据
	gamelogic.standup_clear_seat(table_data.gamelogic, seat)
end

function TableLogic.showcard( table_data, request, seat )	
	gamelogic.showcard(table_data.gamelogic,seat)	
end

function TableLogic.doaction(table_data, request, seat)
	table_data.action_type = request.action_type
	table_data.state = ETableState.TABLE_STATE_CONTINUE
	gamelogic.run(table_data.gamelogic)
end

--- 玩家托管或出牌超时,自动出牌处理函数
-- @param table_data 桌子对象
-- 当轮到该玩家出牌时，服务器根据玩家手牌，筛选出一种类型的牌，打出
-- 目前出牌优先级是(对子>单牌)
function TableLogic.putcards(table_data)
	local seatIndex = table_data.action_seat_index
	local seat = table_data.seats[seatIndex]
	if not seat.cards or #seat.cards <= 0 then
		return false
	end
	local cards = nil
	local putcards = {}
	if not table_data.winner or table_data.conf.blackheart3 == 1 then
		if not table_data.CardsHeaps or #table_data.CardsHeaps == 0 then	-- 第一手牌带了最小牌或黑桃3
			for i = #seat.cards, #seat.cards - 4, -1 do
				if seat.cards[i] < 4 then	-- 有黑桃3找之
					cards = cards or {}
					----加入牌堆中
					-- cards = {seat.cards[i]}
					table.insert(cards, seat.cards[i])
				end
			end
			if cards and #cards == 3 then
				cards = {#seat.cards}
			end
			if not cards then
				local id, mincard = ddzlogic.checkblackheart3(table_data.seats)
				for i = #seat.cards, #seat.cards - 4, -1 do
					if seat.cards[i] < 4 or seat.cards[i] == mincard then
						cards = cards or {}
						----加入牌堆中
						table.insert(cards, seat.cards[i])
					end
				end
			end
			if cards and #cards == 3 then
				cards = {#seat.cards}
			end
			for k,v in ipairs(cards) do
				for m,n in ipairs(seat.cards) do
					if v == n then table.remove(seat.cards,m) end
				end
			end
			putcards = tabletool.deepcopy(cards or {})
			local cardHelper = ddzlogic.CreateCardsHelper(cards)
			cardHelper:GetCardsType(cardHelper)
			if table_data.CardsHeaps == nil then
				table_data.CardsHeaps = {}
				table_data.CardsHeaps[#table_data.CardsHeaps+1] = {}
			end
			local heapOne = {
				rid = seat.rid,
				cardHelper = tabletool.deepcopy(cardHelper)
			}
			table.insert(table_data.CardsHeaps[#table_data.CardsHeaps],heapOne)
			return true, putcards
		end
	end
	local status = false
	local onelast = false
	local onelastindex = nil
	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			if seat.cards and #seat.cards == 1 then
				onelast = true
				onelastindex = seat.index
				break
			end
		end
	end
	if onelast and onelastindex == seatIndex then
		status = true
		cards = {seat.cards[1]}
	-- else
	-- 	status, cards = ddzlogic.deal_last_handscard(seat.cards, ECardsPowerCardType, table_data.action_type, {}, 0, onelast)
	end
	if status == false or not cards or #cards == 0 then
		-- if seat.is_tuoguan == EBOOL.TRUE then
			status, cards = ddzlogic.activePutsCards(seat.cards,1,onelast)
		-- else
		-- 	status = true
		-- 	cards = {seat.cards[#seat.cards]}
		-- end
		if status == false then
			cards = {seat.cards[#seat.cards]}
		end
		if cards == nil or #cards == 0 then
			cards = {seat.cards[#seat.cards]}
		end
		if onelast and #cards == 1 then
			cards = {seat.cards[1]}
		end
	end
	putcards = tabletool.deepcopy(cards or {})
	local cardHelper = ddzlogic.CreateCardsHelper(cards)
	cardHelper:GetCardsType(cardHelper)
	if cardHelper.m_eCardType == ECardType.DDZ_CARD_TYPE_UNKNOWN then
		cards = { seat.cards[#seat.cards] }
		putcards = tabletool.deepcopy(cards or {})
		cardHelper = ddzlogic.CreateCardsHelper(cards)
		cardHelper:GetCardsType(cardHelper)
	end
	if cardHelper.m_eCardType ~= ECardType.DDZ_CARD_TYPE_UNKNOWN then
		----加入牌堆中
		for k,v in ipairs(cards) do
			for m,n in ipairs(seat.cards) do
				if v == n then table.remove(seat.cards,m) end
			end
		end

		if cardHelper.m_eCardType == ECardType.DDZ_CARD_TYPE_BOMB then
			local status
			for _, _seat in ipairs(table_data.seats) do
				if _seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER and _seat.rid > 0 then
					if _seat.rid ~= seat.rid then
						status = ddzlogic.getCardsbyCardType(_seat.cards, cardHelper, true, false)
						break
					end
				end
			end
			if not status then
				table_data.bomb[seat.rid] = (table_data.bomb[seat.rid] or 0) + 1
				local bombadd = 0
				for _, _seat in ipairs(table_data.seats) do
					if _seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER and _seat.rid > 0 then
						if _seat.index ~= seat.index then
							_seat.diamond = _seat.diamond - 10*table_data.conf.base_score
							if table_data.conf.room_type == ERoomType.ROOM_TYPE_COMMON then
								if _seat.diamond < 0 then
									_seat.bomboff = _seat.diamond
									_seat.diamond = 0
								end
								bombadd = bombadd + 10*table_data.conf.base_score + (_seat.bomboff or 0)
							else
								bombadd = bombadd + 10*table_data.conf.base_score
							end
							msghelper:sendmsg_to_alltableplayer("moneychangeN", {
								money_change_list = {
									{
										rid = _seat.rid,
										money_type = 2,
										value = _seat.diamond,
									},
								}
							})
						end
					end
				end
				seat.diamond = seat.diamond + bombadd
				msghelper:sendmsg_to_alltableplayer("moneychangeN", {
					money_change_list = {
						{
							rid = seat.rid,
							money_type = 2,
							value = seat.diamond,
						},
					}
				})
				table_data.bomb_index = nil
			else
				table_data.bomb_index = seatIndex
			end
		end

		if table_data.CardsHeaps == nil then
			table_data.CardsHeaps = {}
			table_data.CardsHeaps[#table_data.CardsHeaps+1] = {}
		end
		local heapOne = {
			rid = seat.rid,
			cardHelper = tabletool.deepcopy(cardHelper)
		}
		table.insert(table_data.CardsHeaps[#table_data.CardsHeaps],heapOne)
		return true, putcards, onelast
	end
	return false
end
--- 在玩家托管或跟牌超时时,服务器自动跟牌
-- @param table_data 桌子对象
--
function TableLogic.followcards(table_data, ischeck, ischaipai)
	local seatIndex = table_data.action_seat_index
	local seat = table_data.seats[seatIndex]
	if not seat.cards or #seat.cards <= 0 then
		return false
	end

	--//出过得牌牌堆里没牌
	local roundheaps = table_data.CardsHeaps[#table_data.CardsHeaps]
	if not roundheaps or #roundheaps <= 0 then
		return false
	end

	local putcards = {}
	local playercardhelper = roundheaps[#roundheaps].cardHelper
	local status, cardtable
	local onelast = false
	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			if seat.cards and #seat.cards == 1 then
				onelast = true
			end
		end
	end
	if onelast and playercardhelper.m_eCardType == ECardType.DDZ_CARD_TYPE_SINGLE then
		status = true
		cardtable = {seat.cards[1]}
	else
		status, cardtable = ddzlogic.deal_last_handscard(seat.cards, ECardsFollowCard, table_data.action_type, playercardhelper, isfindboom)
	end
	if status == false then
		status, cardtable = ddzlogic.getCardsbyCardType(seat.cards,playercardhelper, true, true)
	elseif status == true then
		-- if #cardtable ~= #seat.cards then
		if not cardtable or #cardtable == 0 then
			status, cardtable = ddzlogic.getCardsbyCardType(seat.cards,playercardhelper, true, true)
		end
	end
	if ischeck then
		if status == true then
			local cards = tabletool.deepcopy(cardtable)
			putcards = tabletool.deepcopy(cards or {})
			local cardHelper = ddzlogic.CreateCardsHelper(cards)
			cardHelper:GetCardsType(cardHelper)
			if cardHelper.m_eCardType == ECardType.DDZ_CARD_TYPE_UNKNOWN
				or cardHelper.m_eCardType ~= playercardhelper.m_eCardType then
				return false
			end 
			if cardHelper.m_keyMaxValue <= playercardhelper.m_keyMaxValue then
				return false
			end
			return true, putcards
		elseif status == false then
			return false
		end
	end
	if status == true then
		if cardtable and type(cardtable) == "table" then
			local cards = tabletool.deepcopy(cardtable)
			putcards = tabletool.deepcopy(cards or {})
			local cardHelper = ddzlogic.CreateCardsHelper(cards)
			cardHelper:GetCardsType(cardHelper)
			if (cardHelper.m_eCardType ~= ECardType.DDZ_CARD_TYPE_UNKNOWN and cardHelper.m_eCardType == playercardhelper.m_eCardType
				and cardHelper.m_keyMaxValue > playercardhelper.m_keyMaxValue) or (cardHelper.m_eCardType ~= playercardhelper.m_eCardType and
					(cardHelper.m_eCardType == ECardType.DDZ_CARD_TYPE_ROCKET or cardHelper.m_eCardType == ECardType.DDZ_CARD_TYPE_BOMB) ) then
				for k,v in ipairs(cards) do
					for m,n in ipairs(seat.cards) do
						if v == n then table.remove(seat.cards,m) end
					end
				end

				if cardHelper.m_eCardType == ECardType.DDZ_CARD_TYPE_BOMB then
					local status
					for _, _seat in ipairs(table_data.seats) do
						if _seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER and _seat.rid > 0 then
							if _seat.rid ~= seat.rid then
								status = ddzlogic.getCardsbyCardType(_seat.cards, cardHelper, true, false)
								break
							end
						end
					end
					--[[
					local roundheaps = table_data.CardsHeaps[#table_data.CardsHeaps]
					if roundheaps and #table_data.CardsHeaps > 0 and roundheaps[#roundheaps].cardHelper then
						local roundheap = table_data.CardsHeaps[#table_data.CardsHeaps]
						local helper = roundheap[#roundheap].cardHelper
						local playerid = roundheap[#roundheap].rid
						if helper.m_eCardType == ECardType.DDZ_CARD_TYPE_BOMB and seat.rid ~= playerid then
							table_data.bomb[playerid] = table_data.bomb[playerid] - 1
							assert(table_data.bomb[playerid] >= 0, "error deleting bomb number!!!")
							local bombdel = 0
							local bombindex = nil
							for _, _seat in ipairs(table_data.seats) do
								if _seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER and _seat.rid > 0 then
									 if _seat.rid ~= playerid then
										_seat.diamond = _seat.diamond + 10*table_data.conf.base_score
										if table_data.conf.room_type == ERoomType.ROOM_TYPE_COMMON then
											if _seat.bomboff then
												_seat.diamond = _seat.diamond + _seat.bomboff
											end
											bombdel = bombdel + 10*table_data.conf.base_score + (_seat.bomboff or 0)
											_seat.bomboff = nil
										else
											bombdel = bombdel + 10*table_data.conf.base_score
										end
										msghelper:sendmsg_to_alltableplayer("moneychangeN", {
											money_change_list = {
												{
													rid = _seat.rid,
													money_type = 2,
													value = _seat.diamond,
												},
											}
										})
									else
										bombindex = _seat.index
									end
								end
							end
							table_data.seats[bombindex].diamond = table_data.seats[bombindex].diamond - bombdel
							msghelper:sendmsg_to_alltableplayer("moneychangeN", {
								money_change_list = {
									{
										rid = playerid,
										money_type = 2,
										value = table_data.seats[bombindex].diamond,
									},
								}
							})
						end
					end
					--]]
					if not status then
						table_data.bomb[seat.rid] = (table_data.bomb[seat.rid] or 0) + 1
						local bombadd = 0
						for _, _seat in ipairs(table_data.seats) do
							if _seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER and _seat.rid > 0 then
								if _seat.index ~= seat.index then
									_seat.diamond = _seat.diamond - 10*table_data.conf.base_score
									if table_data.conf.room_type == ERoomType.ROOM_TYPE_COMMON then
										if _seat.diamond < 0 then
											_seat.bomboff = _seat.diamond
											_seat.diamond = 0
										end
										bombadd = bombadd + 10*table_data.conf.base_score + (_seat.bomboff or 0)
									else
										bombadd = bombadd + 10*table_data.conf.base_score
									end
									msghelper:sendmsg_to_alltableplayer("moneychangeN", {
										money_change_list = {
											{
												rid = _seat.rid,
												money_type = 2,
												value = _seat.diamond,
											},
										}
									})
								end
							end
						end
						seat.diamond = seat.diamond + bombadd
						msghelper:sendmsg_to_alltableplayer("moneychangeN", {
							money_change_list = {
								{
									rid = seat.rid,
									money_type = 2,
									value = seat.diamond,
								},
							}
						})
						table_data.bomb_index = nil
					else
						table_data.bomb_index = seatIndex
					end
				end

				if table_data.CardsHeaps == nil then
					table_data.CardsHeaps = {}
					table_data.CardsHeaps[#table_data.CardsHeaps+1] = {}
				end
				local heapOne = {
					rid = seat.rid,
					cardHelper = tabletool.deepcopy(cardHelper)
				}
				table.insert(table_data.CardsHeaps[#table_data.CardsHeaps],heapOne)
				return true, putcards, onelast
			end
		end
	end
	return false
end

function TableLogic.sendHandsInfo(table_data)
	local handsInfo = {}
	handsInfo.basescore = table_data.conf.base_score
	handsInfo.maxscore = table_data.conf.max_score
	handsInfo.times = table_data.conf.baseTimes
	handsInfo.seats = {}
	for k,v in pairs(table_data.seats) do
		local seatInfo = {}
		msghelper:copy_seatinfo(seatInfo,v)
		table.insert(handsInfo.seats,seatInfo)
	end
	msghelper:sendmsg_to_alltableplayer("handsnumN",handsInfo)
end

function TableLogic.score_protected(table_data)
	----计算玩家在牌局中的持有量
	local scores = 0
	local winseat
	local shouldwinall, shouldloseall = 0, 0
	local loseall = 0
	for _, seat in ipairs(table_data.seats) do
		if seat.win == 1 then
			winseat = seat
			break
		end
	end

	local balwinseats = {}
	local balloseseats = {}
	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			if seat.win == 0 then
				local bomblose = seat.getdiamond - seat.diamond	-- 炸弹分数(可能正，可能负)
				local lose = 0
				if #seat.cards > 1 then
					if #seat.cards == table_data.conf.hand_cards_num then
						seat.multiple = 1
					end
					lose = #seat.cards*(table_data.baseTimes + seat.multiple)*table_data.conf.base_score + bomblose
				else
					lose = bomblose
				end
				if lose > 0 then
					loseall = loseall + lose
					balloseseats[seat.index] = {}
					balloseseats[seat.index].lose = lose
				else
					balwinseats[seat.index] = {}
					balwinseats[seat.index].win = -lose
				end
			end
		end
	end
	if table_data.conf.room_type == ERoomType.ROOM_TYPE_COMMON then
		-- 计算跑完牌的玩家的输赢
		local winseatwin = 0
		for k, v in pairs(balwinseats) do
			winseatwin = winseatwin - v.win
		end
		for k, v in pairs(balloseseats) do
			winseatwin = winseatwin + v.lose
		end
		if winseatwin >= 0 then	-- 赢了，放入赢家列表
			balwinseats[winseat.index] = {}
			balwinseats[winseat.index].win = winseatwin
		else -- 输了，放入输家列表
			balloseseats[winseat.index] = {}
			balloseseats[winseat.index].lose = -winseatwin
		end

		-- 赢家预计赢的分数（不能超过携带上限），计入预计总赢数
		for k, v in pairs(balwinseats) do
			if (v.win or 0) > table_data.seats[k].start_diamond then
				shouldwinall = shouldwinall + table_data.seats[k].start_diamond
				v.shouldwin = table_data.seats[k].start_diamond
			else
				shouldwinall = shouldwinall + v.win
				v.shouldwin = v.win
			end
		end
		-- 输家预计输的分数（不能多余拥有数）
		for k, v in pairs(balloseseats) do
			-- filelog.debug("v.lose = ", v.lose,table_data.seats[k].getdiamond)
			if loseall > shouldwinall then
				v.shouldlose = math.floor(v.lose*shouldwinall/loseall)
			else
				v.shouldlose = v.lose
			end
		end
		-- 输家最终输的分数，计入预计总输数
		for k, v in pairs(balloseseats) do
			v.reallose = v.shouldlose > table_data.seats[k].getdiamond and table_data.seats[k].getdiamond or v.shouldlose
			shouldloseall = shouldloseall + v.reallose
			-- filelog.debug("shouldloseall = ", shouldloseall)
		end
		-- filelog.debug("loseall, shouldwinall, shouldloseall", loseall, shouldwinall, shouldloseall)
		-- 赢家最终赢钱
		for k, v in pairs(balwinseats) do
			if shouldwinall <= 0 then
				v.realwin = math.floor(v.shouldwin)
			else
				v.realwin = math.floor(v.shouldwin*shouldloseall/shouldwinall)
			end
		end

		local winseatrealwin = 0 -- 跑完牌的玩家最终输赢，通过其他玩家输赢计算，避免小数导致不能平账
		for _, seat in ipairs(table_data.seats) do
			if seat.index ~= winseat.index then
				if balwinseats[seat.index] then
					seat.balance_score = balwinseats[seat.index].realwin
					-- filelog.debug("player win:", seat.balance_score)
					winseatrealwin = winseatrealwin + seat.balance_score
				elseif balloseseats[seat.index] then	-- 不是输就是赢
					seat.balance_score = -balloseseats[seat.index].reallose
					-- filelog.debug("player lose:", seat.balance_score)
					winseatrealwin = winseatrealwin + seat.balance_score
				end
			end
		end
		winseat.balance_score = -winseatrealwin
		-- filelog.debug("winer loseorwin:", winseat.balance_score)
	else
		local winseatrealwin = 0 -- 跑完牌的玩家最终输赢，通过其他玩家输赢计算，避免小数导致不能平账
		for _, seat in ipairs(table_data.seats) do
			if seat.index ~= winseat.index then
				if balwinseats[seat.index] then
					seat.balance_score = balwinseats[seat.index].win
					-- filelog.debug("player win:", seat.balance_score)
					winseatrealwin = winseatrealwin + seat.balance_score
				elseif balloseseats[seat.index] then	-- 不是输就是赢
					seat.balance_score = -balloseseats[seat.index].lose
					-- filelog.debug("player lose:", seat.balance_score)
					winseatrealwin = winseatrealwin + seat.balance_score
				end
			end
		end
		winseat.balance_score = -winseatrealwin
		-- filelog.debug("winer loseorwin:", winseat.balance_score)
	end
end

function TableLogic.balancegame(table_data)
	TableLogic.score_protected(table_data)
	for k,value in pairs(table_data.seats) do
		if value.rid > 0 then
			--钻石桌结算
			if table_data.conf.room_type == ERoomType.ROOM_TYPE_COMMON then
				value.diamond = value.getdiamond + value.balance_score
				value.playerinfo.diamond = value.diamond

				table_data.tmpdiamond = table_data.tmpdiamond or {}
				table_data.tmpdiamond[value.rid] = {
					rolename = value.playerinfo.rolename,
					beginvalue = math_floor(value.getdiamond),
					value = math_floor(value.diamond - value.getdiamond),
					endvalue = math_floor(value.diamond),
				}
				-- filelog.debug("================>>", value.rid, value.diamond, value.getdiamond, math_floor(value.diamond))
			--//朋友桌结算
			elseif table_data.conf.room_type == ERoomType.ROOM_TYPE_FRIEND then
				value.diamond = value.getdiamond + value.balance_score
				if table_data.cur_games_times == 1 then
					local cardcost = 0
					if not table_data.conf.card_cost_type or table_data.conf.card_cost_type == 1 then
						if value.rid == table_data.conf.create_user_rid then
							cardcost = table_data.conf.card_cost
						end
					else
						if table_data.conf.game_type == EGameType.GAME_TYPE_NORMAL_FOR2 or table_data.conf.game_type == EGameType.GAME_TYPE_CARD15_FOR2 then
							cardcost = math_floor(table_data.conf.card_cost/(table_data.conf.max_player_num - 1))
						else
							cardcost = math_floor(table_data.conf.card_cost/table_data.conf.max_player_num)
						end
					end
					value.fangka = cardcost
				else
					value.fangka = 0
				end
			
				table_data.tablerecords = table_data.tablerecords or {}
				local totalscore_copy = 0
				local onerecordmsg = {}
				onerecordmsg.rid = value.rid
				onerecordmsg.rolename = value.playerinfo.rolename
				onerecordmsg.logo = value.playerinfo.logo
				onerecordmsg.sex = value.playerinfo.sex
				onerecordmsg.highestscore = 0
				onerecordmsg.totalscore = 0
				onerecordmsg.totalwin = 0
				onerecordmsg.totallose = 0
				onerecordmsg.iswin = 0
				local hasplayerkey = 0
				for k,v in ipairs(table_data.tablerecords) do
					if v.rid == value.rid then
						hasplayerkey = k
						break
					end
				end
				local getscore = math_floor(value.diamond - value.getdiamond)
				if hasplayerkey == 0 then
					if getscore > 0 and getscore > onerecordmsg.highestscore then
						onerecordmsg.highestscore = getscore
					end
					onerecordmsg.totalscore = onerecordmsg.totalscore + getscore
					totalscore_copy = onerecordmsg.totalscore
					if value.win == 1 then
						onerecordmsg.totalwin = onerecordmsg.totalwin + 1 
					elseif value.win == 0 then
						onerecordmsg.totallose = onerecordmsg.totallose + 1 
					end
					table.insert(table_data.tablerecords, onerecordmsg)
				elseif hasplayerkey > 0 then
					local playerrecord = table_data.tablerecords[hasplayerkey]
					if playerrecord then
						if getscore > 0 and getscore > playerrecord.highestscore then
							playerrecord.highestscore = getscore
						end
						playerrecord.totalscore = playerrecord.totalscore + getscore
						totalscore_copy = playerrecord.totalscore
						playerrecord.rolename = value.playerinfo.rolename
						playerrecord.sex = value.playerinfo.sex
						if value.win == 1 then
							playerrecord.totalwin = playerrecord.totalwin + 1 
						elseif value.win == 0 then
							playerrecord.totallose = playerrecord.totallose + 1 
						end
					end
				end
			end
		end
		value.getdiamond = value.diamond
	end
	if table_data.conf.room_type == ERoomType.ROOM_TYPE_COMMON then
		TableLogic.change_all_player_money(table_data)
	elseif table_data.conf.room_type == ERoomType.ROOM_TYPE_FRIEND then
		if table_data.cur_games_times == 1 then
			TableLogic.pay_roomcard(table_data)
		end
		-- local commnet = {
		-- 	table_tradeid = skynet.call(".nodeuuid", "lua", "getuuid"),	
		-- }
		-- TableLogic.save_gamerecords(table_data, commnet)
	end
end

function TableLogic.save_actions(table_data, action, cards)
	if table_data.conf.room_type ~= ERoomType.ROOM_TYPE_COMMON and table_data.conf.room_type ~= ERoomType.ROOM_TYPE_COIN then
		return
	end
	local records = table_data.gamerecords
	if type(records) ~= type{} or not records.logname then
		filelog.sys_error("save actions error: no records")
		return
	end
	local logstr = ''
	if not action then
		logstr = logstr
			.. (records.table_uuid or '0') .. '\n'
			.. table_data.conf.room_type .. '\n'
			.. (records.tip or '0') .. '\n'
			.. (records.conf or "{}") .. '\n'
			.. (records.start_time or '0') .. '\n'
			.. (records.playerdata or '{}') .. '\n'
			.. (records.initcards or "{}") .. '\n'				-- 初始牌堆
			.. (records.handcards or "{}")
	else
		if type(action) == type{} then
			logstr = logstr .. json.encode(action)
		elseif action == "end" then
			logstr = logstr .. action
		else
			logstr = logstr .. action .. '_'
				.. "cards:" .. (json.encode(cards or {}))
		end
	end
	-- filelog.info("logstr = ", logstr)
	skynet.call(".tablereplaylog", "lua", "write", records.logname, logstr)
end

function TableLogic.save_gamerecords(table_data, commnet)
	local records = table_data.gamerecords
	if type(records) ~= type{} or not records.logname then
		filelog.sys_error("save game records error: no records")
		return
	end

	local diamondinfo = {}
	local balanceinfo = {}
	local rids = ''
	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			if table_data.tmpdiamond and table_data.tmpdiamond[seat.rid] then
				table.insert(diamondinfo, {
					rid = seat.rid,
					rolename = table_data.tmpdiamond[seat.rid].rolename,
					value = table_data.tmpdiamond[seat.rid].value,
				})
				balanceinfo[seat.rid] = {
					winvalue = table_data.tmpdiamond[seat.rid].value,
					gamestar_diamond = table_data.tmpdiamond[seat.rid].beginvalue,
					gameend_diamond = table_data.tmpdiamond[seat.rid].endvalue,
				}
			end
			if rids == '' then
				rids = rids .. seat.rid
			else
				rids = rids .. '_' .. seat.rid
			end
		end
	end

	local ts = timetool.get_time()
	local logname = '' .. records.table_uuid .. '_'
		.. records.start_time .. '_' .. ts .. '_'
		.. (records.rids or rids) .. '_' .. os.date("%Y%m%d_%H%M%S", records.start_time or 0)
	-- filelog.debug("logname = ", logname)
	local logstr = ''
		.. (records.table_uuid or '0') .. '\n'
		.. table_data.conf.room_type .. '\n'
		.. (records.tip or '0') .. '\n'
		.. (records.conf or "{}") .. '\n'
		.. (records.start_time or '0') .. '\n'
		.. timetool.get_time() .. '\n'
		.. json.encode(balanceinfo) .. '\n'
		.. commnet.table_tradeid .. '\n'
		.. json.encode(diamondinfo) .. '\n'
		.. json.encode({}) .. '\n'				-- 结算算番情况
		.. (records.initcards or "{}") .. '\n'	-- 初始牌堆

	-- filelog.debug("logstr = ", logstr)
	skynet.call(".tablerecordlog", "lua", "write", logname, logstr, records.handcards or "{}")
end

local function caclate_tip(base)
	return math_ceil(base*0.3)
end

function TableLogic.pay_tip(table_data)
	local base_cost = table_data.conf.base_score
	local data = {}	
	local tip = caclate_tip(base_cost)
	tip = tip >= 0 and tip or 0
	table_data.tip = tip
	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			data[seat.rid] = {
				beginvalue = seat.getdiamond,
				value = tip,
				endvalue = 0,
			}
			seat.diamond = seat.diamond - tip
			seat.getdiamond = seat.getdiamond - tip
			seat.playerinfo.diamond = seat.diamond
			data[seat.rid].endvalue = seat.getdiamond
		end
	end
	local commnet = {
		table_uuid = table_data.gamerecords.table_uuid,		
		table_tradeid = skynet.call(".nodeuuid", "lua", "getuuid"),
		start_time = table_data.gamerecords.start_time,
	}
	msghelper:sendmsg_to_gatesvr("game_sub_fuwufei", data, commnet)
	table_data.gamerecords.tip = tip
	-- msghelper:sendmsg_to_alltableplayer("paytipN", {
	-- 	tip = tip,
	-- })
end

function TableLogic.pay_roomcard(table_data)
	local data = {}
	for _, seat in ipairs(table_data.seats) do
		if seat.state ~= ESeatState.SEAT_STATE_NO_PLAYER then
			seat.playerinfo.fangka = seat.playerinfo.fangka - seat.fangka
			data[seat.rid] = {
				value = seat.fangka*100,
			}
		end
	end
	local commnet = {
		table_uuid = skynet.getenv("nodename") .. "_" .. table_data.conf.table_code .. "_" .. table_data.conf.idx .. "_" .. timetool.get_time(),		
		table_tradeid = skynet.call(".nodeuuid", "lua", "getuuid"),	
	}
	msghelper:sendmsg_to_gatesvr("game_sub_fangka", data, commnet)
end

function TableLogic.change_all_player_money(table_data)
	if not table_data.tmpdiamond then
		filelog.sys_error("no data for changing player money,is somewhere error???")
		return
	end

	local records = table_data.gamerecords
	if type(records) ~= type{} or not records.logname then
		filelog.sys_error("change all player money error: no records")
		return
	end

	--[[强行平账,正常不应该出现
	local offset = 0
	local rid
	for k, v in pairs(table_data.tmpdiamond) do
		offset = offset + v.value
		if v.value > 0 then
			rid = k
		end
	end
	if offset ~= 0 then
		local beginvalue = table_data.tmpdiamond[rid].beginvalue - offset
		local value = table_data.tmpdiamond[rid].value - offset
		local endvalue = beginvalue + value
		table_data.tmpdiamond[rid] = {
			rolename = table_data.tmpdiamond[rid].rolename,
			beginvalue = beginvalue,
			value = value,
			endvalue = endvalue,
		}
		filelog.sys_error("change_all_player_money serious error:offset not 0: ", offset, table_data.tmpdiamond, commnet)
	end
	--]]

	local commnet = {
		table_uuid = records.table_uuid,
		table_tradeid = skynet.call(".nodeuuid", "lua", "getuuid"),
		start_time = records.start_time or '0',
		replay_logname = records.logname,
	}
	msghelper:sendmsg_to_gatesvr("game_balance_diamond", table_data.tmpdiamond, commnet)
	filelog.trace("change all player money: ", table_data.tmpdiamond, commnet)
	-- TableLogic.save_gamerecords(table_data, commnet)
end

function TableLogic.save_tablerecord(table_data, record)
	if not record then
		filelog.sys_error("no data for save_table_record,is somewhere error???")
		return
	end

	local records = table_data.gamerecords
	if type(records) ~= type{} or not records.logname then
		filelog.sys_error("save_table_record error: no records")
		return
	end

	local commnet = {
		table_uuid = records.table_uuid,
		table_tradeid = skynet.call(".nodeuuid", "lua", "getuuid"),
		start_time = records.start_time or '0',
	}
	-- filelog.debug("save_table_record:", record, commnet)
	msghelper:sendmsg_to_gatesvr("game_balance_fangka", record, commnet)
end

function TableLogic.get_sitdown_player_num(table_data)
	return table_data.sitdown_player_num
end

--根据指定桌位号获得一张空座位
function TableLogic.get_emptyseat_by_index(table_data)
	for index, seat in pairs(table_data.seats) do
		if seatlogic.is_empty(seat) then
			return seat
		end
	end
	return nil
end

function TableLogic.get_seat_by_rid(table_data, rid)
	for index, seat in pairs(table_data.seats) do
		if rid == seat.rid then
			return seat
		end
	end
	return nil
end

--判断桌子是否满了
function TableLogic.is_full(table_data)
	if table_data.conf.game_type == EGameType.GAME_TYPE_NORMAL_FOR2 or table_data.conf.game_type == EGameType.GAME_TYPE_CARD15_FOR2 then
		return table_data.sitdown_player_num >= (table_data.conf.max_player_num - 1)
	else
		return table_data.sitdown_player_num >= table_data.conf.max_player_num
	end
end

--判断当前是否能够开始游戏
function TableLogic.is_canstartgame(table_data)
	if table_data.conf.game_type == EGameType.GAME_TYPE_NORMAL_FOR2 or table_data.conf.game_type == EGameType.GAME_TYPE_CARD15_FOR2 then
		return table_data.sitdown_player_num >= (table_data.conf.max_player_num - 1)
	else
		return table_data.sitdown_player_num >= table_data.conf.max_player_num
	end
end

--判断游戏是否结束
function TableLogic.is_gameend(table_data)
	if table_data.state == ETableState.TABLE_STATE_WAIT_GAME_START
		or table_data.state == ETableState.TABLE_STATE_WAIT_ALL_READY then
		return true
	end
	return false
end

--判断当前局是否已经结束游戏
function TableLogic.is_onegameend(table_data)
	return (not table_data.gaming)
end

return TableLogic
